package br.com.marcelo.reservasis.client.pagina.reserva;

import br.com.aroeirasoftware.gwtcomponents.client.components.ASApplication;
import br.com.aroeirasoftware.gwtcomponents.client.components.ASButton;
import br.com.aroeirasoftware.gwtcomponents.client.components.ASComboBox;
import br.com.aroeirasoftware.gwtcomponents.client.components.ASFieldSize;
import br.com.aroeirasoftware.gwtcomponents.client.components.ASForm;
import br.com.aroeirasoftware.gwtcomponents.client.components.ASMessagePanel;
import br.com.aroeirasoftware.gwtcomponents.client.components.ASOperation;
import br.com.aroeirasoftware.gwtcomponents.client.components.ASPage;
import br.com.aroeirasoftware.gwtcomponents.client.components.ASPair;
import br.com.aroeirasoftware.gwtcomponents.client.components.ASPopupMenu;
import br.com.aroeirasoftware.gwtcomponents.client.components.ASResource;
import br.com.aroeirasoftware.gwtcomponents.client.components.ASTableColumn;
import br.com.aroeirasoftware.gwtcomponents.client.components.ASTablePaged;
import br.com.aroeirasoftware.gwtcomponents.client.components.ASTogglePanel;
import br.com.aroeirasoftware.gwtcomponents.client.i18n.ASGWTComponentsI18N;
import br.com.aroeirasoftware.gwtcomponents.client.query.ASQuery;
import br.com.aroeirasoftware.gwtcomponents.client.query.ASQueryObject;
import br.com.aroeirasoftware.gwtcomponents.client.query.ASQueryResult;
import br.com.marcelo.reservasis.client.componentes.ReservaSISApplication;
import br.com.marcelo.reservasis.client.componentes.ReservaSISResources;
import br.com.marcelo.reservasis.client.i18n.ReservaSISI18N;
import br.com.marcelo.reservasis.client.services.reservaestadia.ReservaEstadiaUIService;
import br.com.marcelo.reservasis.client.util.ComboBoxUtil;
import br.com.marcelo.reservasis.domain.model.ReservaEstadia;
import br.com.marcelo.reservasis.domain.model.TipoApartamento;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DeferredCommand;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.UIObject;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 *
 * @author Marcelo Rodrigues
 */
public class ReservaEstadiaPesquisarPagina extends ASPage {

    private ClickHandler clickHandler;
    private ASButton bPesquisar;
    private ASButton bLimpar;
    private ASButton bCadastrarReserva;
    private ASButton bCadastrarHospedagem;
    private ASButton bFechar;
    private ASForm formulario;
    private ASTogglePanel painel;
    private ASTablePaged<ReservaEstadia> tabela;
//    private ASPopupMenu<ReservaEstadia> popupMenu;
    private ASResource recurso;
    private List<ASOperation> operacoesDisponiveis;
    private ASOperation[] operacoes;
    private ASQuery consulta;
    private ASTableColumn[] colunas;
    private DateTimeFormat dtf;
    public static final String OPERACAO_CADASTRAR_RESERVA = "cadastrarReserva";
    public static final String OPERACAO_CADASTRAR_HOSPEDAGEM = "cadastrarHospedagem";
    public static final String OPERACAO_ALTERAR = "alterar";
    public static final String OPERACAO_EXCLUIR = "excluir";
    public static final String OPERACAO_DETALHAR = "detalhar";
    public static final String OPERACAO_SELECIONAR = "selecionar";

    public ReservaEstadiaPesquisarPagina(ASPage paginaAnterior, ASApplication aplicacao, String titulo, String subtitulo) {
        super(paginaAnterior, aplicacao, titulo, subtitulo);
        this.operacoes = new ASOperation[]{ASOperation.CRIACAO, ASOperation.ALTERACAO, ASOperation.EXCLUSAO, ASOperation.LEITURA};
        this.recurso = ReservaSISResources.RESERVAESTADIA();
        this.colunas = new ASTableColumn[]{new ASTableColumn(0, ReservaSISI18N.messages.apartamento(), "texto-centro", "texto-centro", "15%"),
                    new ASTableColumn(1, ReservaSISI18N.messages.hospede(), "texto-centro", "texto-esquerda", "30%"),
                    new ASTableColumn(2, ReservaSISI18N.messages.dataChegada(), "texto-centro", "texto-centro", "15%"),
                    new ASTableColumn(3, ReservaSISI18N.messages.quartos(), "texto-centro", "texto-centro", "10%"),
                    new ASTableColumn(4, ReservaSISI18N.messages.tipo(), "texto-centro", "texto-centro", "20%"),
                    new ASTableColumn(5, ReservaSISI18N.messages.status(), "texto-centro", "texto-centro", "10%")};
        this.operacoesDisponiveis = new ArrayList<ASOperation>();
    }

    @Override
    public void configurarComponentes() {
        dtf = DateTimeFormat.getFormat("dd/MM/yyyy");
        for (ASOperation operacao : operacoes) {
            this.operacoesDisponiveis.add(operacao);
        }

        this.clickHandler = new ClickHandler() {

            public void onClick(ClickEvent event) {
                ASButton<ReservaEstadia> source = (ASButton<ReservaEstadia>) event.getSource();

                if (source == bPesquisar) {
                    bloquearPesquisa();

                    if (formulario.isValido()) {
                        DeferredCommand.addCommand(new Command() {

                            public void execute() {
                                pesquisar(formulario.getValue());
                            }
                        });
                    }
                }

                if (source == bLimpar) {
                    limpar();
                }

                if (source == bCadastrarReserva) {
                    executar(null, OPERACAO_CADASTRAR_RESERVA);
                }

                if (source == bCadastrarHospedagem) {
                    executar(null, OPERACAO_CADASTRAR_HOSPEDAGEM);
                }

                if (source == bFechar) {
                    fechar();
                }
            }
        };

        bPesquisar = new ASButton(ASGWTComponentsI18N.messages.btnPesquisar(), clickHandler);
        bPesquisar.addEstiloDefault();
        addComando(bPesquisar);

        bLimpar = new ASButton(ASGWTComponentsI18N.messages.btnLimpar(), clickHandler);
        addComando(bLimpar);

        if (this.operacoesDisponiveis.contains(ASOperation.CRIACAO)
                && getAplicacao().isRecursoOperacaoDisponivel(this.recurso, ASOperation.CRIACAO)) {
            bCadastrarReserva = new ASButton(ReservaSISI18N.messages.btnCadastrarReserva(), clickHandler);
            bCadastrarHospedagem = new ASButton(ReservaSISI18N.messages.btnCadastrarHospedagem(), clickHandler);
            addComando(bCadastrarReserva);
            addComando(bCadastrarHospedagem);
        }

        bFechar = new ASButton(ASGWTComponentsI18N.messages.btnFechar(), clickHandler);
        addComando(bFechar);


        /*
         * Criando o formulário de pesquisa
         */
        formulario = new ASForm();

        formulario.addCampoTextoData("dataMarcacao", ReservaSISI18N.messages.dataMarcacao(), false);
        formulario.addCampoTextoData("dataChegada", ReservaSISI18N.messages.dataChegada(), false);
        formulario.addCampoOpcoesComboBox("tipoApartamento", ReservaSISI18N.messages.tipoApartamento(), false, true);
        formulario.addCampoOpcoesComboBox("status", ReservaSISI18N.messages.status(), false, true, new ASPair<Object, String>(0, ReservaSISI18N.messages.reservaOk()),
                new ASPair<Object, String>(1, ReservaSISI18N.messages.reservado()),
                new ASPair<Object, String>(2, ReservaSISI18N.messages.hospedado()));
        formulario.addCampoTexto("hospede", ReservaSISI18N.messages.hospede(), false, ASFieldSize.GRANDE);

        painel = new ASTogglePanel(ASGWTComponentsI18N.messages.geralCriteriosPesquisa());
        painel.add(formulario);
        painel.setWidth("100%");

        add(painel);

        List<ASTableColumn> colunasTabela = new ArrayList<ASTableColumn>();

        for (ASTableColumn coluna : colunas) {
            colunasTabela.add(coluna);
        }

        if (!this.operacoesDisponiveis.isEmpty()) {
            colunasTabela.add(new ASTableColumn(colunasTabela.size(),
                    ASGWTComponentsI18N.messages.geralOpcoes(),
                    "texto-centro", "texto-centro", "15%"));
        }

        tabela = new ASTablePaged<ReservaEstadia>(true, colunasTabela.toArray(new ASTableColumn[0])) {

            @Override
            public void paginar(int pagina) {
                bloquearPesquisa();
                ReservaEstadiaPesquisarPagina.this.paginar(pagina);
            }

            @Override
            public void renderizarLinha(final ReservaEstadia t) {

                //Criando o ASPopupMenu<ReservaEstadia> padrao com alteraçao, detalhes e exclusao
                final ASPopupMenu<ReservaEstadia> popupMenu = new ASPopupMenu<ReservaEstadia>();
                if (!operacoesDisponiveis.contains(ASOperation.SELECAO)) {

                    if (operacoesDisponiveis.contains(ASOperation.ALTERACAO)
                            && getAplicacao().isRecursoOperacaoDisponivel(recurso, ASOperation.ALTERACAO)) {

                        popupMenu.addComando(ASGWTComponentsI18N.images.pencil(),
                                ASGWTComponentsI18N.messages.btnAlterar(), new Command() {

                            public void execute() {
                                popupMenu.fechar();
                                executar(popupMenu.getValue(), OPERACAO_ALTERAR);
                            }
                        });
                    }

                    if (operacoesDisponiveis.contains(ASOperation.EXCLUSAO)
                            && getAplicacao().isRecursoOperacaoDisponivel(recurso, ASOperation.EXCLUSAO)) {
                        popupMenu.addComando(ASGWTComponentsI18N.images.crossButton(),
                                ASGWTComponentsI18N.messages.btnExcluir(), new Command() {

                            public void execute() {
                                popupMenu.fechar();

                                ASMessagePanel.getInstance().exibirMensagem(
                                        ASGWTComponentsI18N.messages.msgConfirma(),
                                        ASMessagePanel.ASMessageSeverity.AVISO,
                                        ASMessagePanel.ASMessageOption.SIM_NAO, new Command() {

                                    public void execute() {
                                        if (ASMessagePanel.getInstance().getOpcaoSelecionada() == ASMessagePanel.ASMessageOptionReturn.SIM) {
                                            tabela.removeLinha(popupMenu.getValue(), popupMenu.getLinhaTabela());
                                            executar(popupMenu.getValue(), OPERACAO_EXCLUIR);
                                        }
                                    }
                                });
                            }
                        });
                    }

                    if (operacoesDisponiveis.contains(ASOperation.LEITURA)
                            && getAplicacao().isRecursoOperacaoDisponivel(recurso, ASOperation.LEITURA)) {
                        popupMenu.addComando(ASGWTComponentsI18N.images.eye(),
                                ASGWTComponentsI18N.messages.btnDetalhar(), new Command() {

                            public void execute() {
                                popupMenu.fechar();
                                executar(popupMenu.getValue(), OPERACAO_DETALHAR);
                            }
                        });
                    }
                }

                //Buscando  ReservaEstadia por ID paara ser usado na tabela
                ReservaEstadiaUIService.Async.getInstance().getPorId(t.getIdreserva(), new AsyncCallback<ReservaEstadia>() {

                    @Override
                    public void onFailure(Throwable caught) {
                        ASMessagePanel.getInstance().exibirMensagem(
                                ReservaSISI18N.messages.msgErro(ReservaSISI18N.messages.gPesquisar(), caught),
                                ASMessagePanel.ASMessageSeverity.ERRO,
                                ASMessagePanel.ASMessageOption.OK, new Command() {

                            public void execute() {
                                liberarPesquisa();
                            }
                        });
                    }

                    @Override
                    public void onSuccess(ReservaEstadia result) {

                        final ReservaEstadia re = result;

                        String dataChegada = "";

                        if (re.getDatachegada() != null) {
                            dataChegada = dtf.format(re.getDatachegada());
                        }

                        addCelula(ReservaSISI18N.messages.hospede(), re.getHospede() != null ? re.getHospede().getNome() : "");
                        addCelula(ReservaSISI18N.messages.dataChegada(), dataChegada);
                        addCelula(ReservaSISI18N.messages.status(), re.getReservaDescricao());
                        addCelula(ReservaSISI18N.messages.apartamento(), re.getApartamento().getNumApart().toString());
                        addCelula(ReservaSISI18N.messages.quartos(), re.getApartamento().getNumQuartosApart().toString());
                        addCelula(ReservaSISI18N.messages.tipo(), re.getApartamento().getTipoApartamento().getDescricao());

                        if (!operacoesDisponiveis.isEmpty()) {
                            ASButton<ReservaEstadia> bAcao = new ASButton<ReservaEstadia>();
                            bAcao.addClickHandler(clickHandler);
                            bAcao.addEstiloMini();
                            bAcao.setValue(t);

                            if (operacoesDisponiveis.contains(ASOperation.SELECAO)) {
                                bAcao.setHTML(ASGWTComponentsI18N.messages.btnSelecionar());
                                bAcao.setOperacao(ASOperation.SELECAO);
                            } else {
                                bAcao.setHTML(ASGWTComponentsI18N.messages.btnAbrir());
                                bAcao.setOperacao(null);

                                //Adicionando menus ao PopMenu de acordo com os status da reserva.
                                if (re.getReservaDescricao().equals("Hospedado")) {
                                    popupMenu.addComando(ASGWTComponentsI18N.images.eye(),
                                            ASGWTComponentsI18N.messages.btnDetalhar(), new Command() {

                                        public void execute() {
                                            popupMenu.fechar();
                                            Window.alert("teste funfou");
                                        }
                                    });
                                }
                            }
                            bAcao.addClickHandler(new ClickHandler() {

                                @Override
                                public void onClick(ClickEvent event) {
                                    popupMenu.abrir((UIObject) event.getSource(), re, tabela.getCellForEvent(event).getRowIndex());
                                }
                            });
                            addCelula(ASGWTComponentsI18N.messages.geralOpcoes(), bAcao);
                        }
                    }
                });

            }
        };
        tabela.setVisible(false);
        add(tabela);
        carregarComboBox();
    }

    @Override
    public void abrir() {
        if (getAplicacao().isRecursoOperacaoDisponivel(recurso, ASOperation.LEITURA)) {
            super.abrir();
        } else {
            ASMessagePanel.getInstance().exibirMensagem(
                    ASGWTComponentsI18N.messages.msgSemPermissaoRecurso(),
                    ASMessagePanel.ASMessageSeverity.ERRO,
                    ASMessagePanel.ASMessageOption.OK);
        }
    }

    public void setResultadoPesquisa(int pagina, int paginas, List<ReservaEstadia> lista) {
        tabela.setLinhas(pagina, paginas, lista);

        if (lista.isEmpty()) {
            ASMessagePanel.getInstance().exibirMensagem(
                    ASGWTComponentsI18N.messages.msgNenhumaInformacaoEncontrada(),
                    ASMessagePanel.ASMessageSeverity.AVISO,
                    ASMessagePanel.ASMessageOption.OK);
            tabela.setVisible(false);
        }

        liberarPesquisa();
    }

    public void setResultadoPesquisa(ASQueryResult<ReservaEstadia> resultado) {
        setResultadoPesquisa(resultado.getPagina(), resultado.getPaginas(), resultado.getLista());
    }

    public Map<String, Object> getParametrosPesquisa() {
        return formulario.getValue();
    }

    @Override
    public void configurarDados() {
    }

    public void bloquearPesquisa() {
        DeferredCommand.addCommand(new Command() {

            public void execute() {
                getAplicacao().getLayout().exibirStatus();
            }
        });

        bPesquisar.setEnabled(false);
        bPesquisar.setHTML(ASGWTComponentsI18N.messages.geralProcessando());
    }

    public void liberarPesquisa() {
        bPesquisar.setHTML(ASGWTComponentsI18N.messages.btnPesquisar());
        bPesquisar.setEnabled(true);
        getAplicacao().getLayout().ocultarStatus();
    }

    public void limpar() {
        tabela.removeLinhas();
        tabela.setVisible(false);
        formulario.limparCampos();
        formulario.focalizarPrimeiroCampo();
        liberarPesquisa();
    }

    public void pesquisar(Map<String, Object> parametros) {
        ASQueryObject qo = new ASQueryObject(ReservaEstadia.class, "re");
        qo.addSelect(ASQueryObject.Expressions.as("re.idreserva", "idreserva")).
                addSelect(ASQueryObject.Expressions.as("re.apartamento", "apartamento")).
                addSelect(ASQueryObject.Expressions.as("re.datamarcacao", "datamarcacao")).
                addSelect(ASQueryObject.Expressions.as("re.datachegada", "datachegada")).
                addSelect(ASQueryObject.Expressions.as("re.reserva", "reserva"));

        qo.addWhere(ASQueryObject.Expressions.eq("re.datamarcacao", parametros.get("dataMarcacao")));
        qo.addWhere(ASQueryObject.Expressions.eq("re.datachegada", parametros.get("dataChegada")));
        qo.addWhere(ASQueryObject.Expressions.eq("re.apartamento.tipoApartamento", parametros.get("tipoApartamento")));
        qo.addWhere(ASQueryObject.Expressions.eq("re.reserva", parametros.get("status")));
        qo.addWhere(ASQueryObject.Expressions.likeFull("re.hospede", parametros.get("hospede")));

        consulta = qo.getConsulta(ASQueryObject.Expressions.count("re.idreserva", "idreserva"), true, 5);

        paginar(1);
    }

    public void paginar(int pagina) {
        consulta.setPagina(pagina);
        ReservaEstadiaUIService.Async.getInstance().getPorConsulta(consulta, new AsyncCallback<ASQueryResult<ReservaEstadia>>() {

            public void onFailure(Throwable caught) {
                ASMessagePanel.getInstance().exibirMensagem(
                        ReservaSISI18N.messages.msgErro(ReservaSISI18N.messages.gPesquisar(), caught),
                        ASMessagePanel.ASMessageSeverity.ERRO,
                        ASMessagePanel.ASMessageOption.OK, new Command() {

                    public void execute() {
                        liberarPesquisa();
                    }
                });
            }

            public void onSuccess(ASQueryResult<ReservaEstadia> result) {
                setResultadoPesquisa(result.getPagina(), result.getPaginas(), result.getLista());
            }
        });
    }

    public void executar(ReservaEstadia t, String nomeOperacao) {
        if (nomeOperacao.equals(OPERACAO_CADASTRAR_RESERVA)) {
            new ReservaCriarAlterarPagina(this, ReservaSISApplication.getInstance(), ReservaSISI18N.messages.tituloReservaEstadiaCriarPagina(), ReservaSISI18N.messages.subtituloReservaEstadiaCriarPagina("asterisco")).abrir();
        } else if (nomeOperacao.equals(OPERACAO_CADASTRAR_HOSPEDAGEM)) {
            new HospedagemCriarAlterarPagina(this, ReservaSISApplication.getInstance(), ReservaSISI18N.messages.tituloHospedagemCriarPagina(), ReservaSISI18N.messages.subtituloHospedagemCriarPagina("asterisco")).abrir();
        } else if (nomeOperacao.equals(OPERACAO_DETALHAR)) {
            Window.alert("teste detalhar");
        } else if (nomeOperacao.equals(OPERACAO_ALTERAR)) {
            Window.alert("teste alterar");
        } else if (nomeOperacao.equals(OPERACAO_EXCLUIR)) {
            Window.alert("teste excluir");
        }
    }

    public void carregarComboBox() {
        ComboBoxUtil.preencherComboBoxTipoApartamento((ASComboBox<TipoApartamento>) formulario.getCampo("tipoApartamento").getComponente());
    }
}
